package com.aizuda.easyManagerTool.service.terminal.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.aizuda.easy.security.domain.Rep;
import com.aizuda.easy.security.domain.Req;
import com.aizuda.easy.security.server.EasySecurityServer;
import com.aizuda.easyManagerTool.config.YmlVarConfig;
import com.aizuda.easyManagerTool.domian.dto.terminal.SFTPFileDTO;
import com.aizuda.easyManagerTool.domian.dto.terminal.SSHMessageDTO;
import com.aizuda.easyManagerTool.domian.vo.server.ServerCompleteVO;
import com.aizuda.easyManagerTool.domian.vo.setting.SettingUserVO;
import com.aizuda.easyManagerTool.domian.vo.socket.SocketMessageVO;
import com.aizuda.easyManagerTool.domian.vo.terminal.SFTPFileVO;
import com.aizuda.easyManagerTool.mapper.server.ServerMapper;
import com.aizuda.easyManagerTool.service.socket.SocketEventService;
import com.aizuda.easyManagerTool.service.socket.impl.SocketSessionManager;
import com.aizuda.easyManagerTool.service.terminal.ExecuteService;
import com.aizuda.easyManagerTool.util.SSHManagerUtil;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.SftpATTRS;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;
import java.util.Vector;
import java.util.stream.Collectors;


@Service("sftp")
@Slf4j
public class SFTPServiceImpl extends AbstractTerminalTemplate implements ExecuteService, SocketEventService{

    SFTPFileVO sftpFileVO = new SFTPFileVO();
    SocketMessageVO socketMessageVO = new SocketMessageVO();
    @Resource
    YmlVarConfig ymlVarConfig;
    @Resource
    ServerMapper serverMapper;
    @Resource
    EasySecurityServer easySecurityServer;

    @Override
    public Rep<List<SFTPFileVO>> del(Req<SFTPFileDTO, SettingUserVO> req) {
        try {
            SFTPFileDTO data = req.getData();
            SettingUserVO authUser = (SettingUserVO) easySecurityServer.getAuthUser(data.getToken().substring(0,data.getToken().indexOf(":")));
            String token = authUser.getId()+":"+authUser.getTenantId()+data.getToken().substring(data.getToken().indexOf(":"));
            TerminalSessionManager.Manager manager = TerminalSessionManager.getManager(data.getToken());
            ChannelSftp channelSftp = manager.getChannelSftp();
            if(data.getIsDir()){
                // 删除所有文件
                SSHManagerUtil.setChannelExec(manager.getSession(),manager,"rm -rf "+data.getPath());
            }else {
                channelSftp.rm(data.getPath());
            }
            String  newPath = data.getPath().substring(0,data.getPath().lastIndexOf("/")+1);
            Vector<ChannelSftp.LsEntry> vector = channelSftp.ls(newPath);
            List<SFTPFileVO> sftpFileVOS = analysisLsEntry(vector);
            SocketMessageVO<List<SFTPFileVO>> messageVO = BeanUtil.copyProperties(socketMessageVO, SocketMessageVO.class);
            messageVO.setType("sftp");
            messageVO.setObj(sftpFileVOS);
            WebSocketSession webSocketSession = SocketSessionManager.get(token);
            webSocketSession.sendMessage(new TextMessage(JSONUtil.toJsonStr(messageVO)));
        } catch (Exception e) {
            return Rep.error(500,"删除失败 :"+e.getMessage());
        }
        return Rep.ok();
    }

    @Override
    public Rep<String> upload(String path, String token, MultipartFile file) {
        try {
            InputStream inputStream = file.getInputStream();
            if (file.isEmpty()) {
                return Rep.error(500,"上传失败，请选择文件");
            }
            TerminalSessionManager.Manager manager = TerminalSessionManager.getManager(token);
            synchronized (manager) {
                ChannelSftp channelSftp = manager.getChannelSftp();
                channelSftp.cd(path);
                String pathFile = file.getOriginalFilename();
                if (pathFile.lastIndexOf("/") != -1) {
                    String dir = pathFile.substring(0, pathFile.lastIndexOf("/"));
                    try {
                        // 校验文件是否存在，不存在会报错
                        channelSftp.ls(dir);
                    }catch (Exception e){
                        // 不存在则逐级创建
                        String[] split = dir.split("/");
                        String p = "";
                        for (int i = 0; i < split.length; i++) {
                            p += split[i]+"/";
                            try{
                                channelSftp.mkdir(p);
                            }catch (Exception ex){
                                // 重复创建会报错
                            }
                        }
                    }
                }
                channelSftp.put(inputStream, file.getOriginalFilename());
                inputStream.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return Rep.ok();
    }

    @Override
    public Rep<String> download(Req<SFTPFileDTO, SettingUserVO> req, HttpServletRequest request) {
        try {
            SFTPFileDTO sftpFileDTO = req.getData();
            String name = sftpFileDTO.getFileName();
            String suffix = "";
            if(name.lastIndexOf(".") != -1) {
                suffix = name.substring(name.lastIndexOf("."));
            }
            String fileName = System.currentTimeMillis()+suffix;
            TerminalSessionManager.Manager manager = TerminalSessionManager.getManager(sftpFileDTO.getToken());
            ChannelSftp channelSftp = manager.getChannelSftp();
            File file = new File(ymlVarConfig.getPath()+fileName);
            // 下载到服务器，然后由 bff 在去下载
            channelSftp.cd(sftpFileDTO.getPath());
            channelSftp.get(sftpFileDTO.getFileName(), new FileOutputStream(file));
            return Rep.ok(ymlVarConfig.getFullPath()+fileName);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return Rep.error(500,"下载失败");
    }

    @Override
    void init(String token,WebSocketSession message, TerminalSessionManager.Manager manager, SSHMessageDTO messageDTO) throws Exception {
        ServerCompleteVO serverCompleteVO = serverMapper.findById(messageDTO.getServerId());
        BeanUtil.copyProperties(serverCompleteVO,messageDTO.getInfo());
        try {
            SSHManagerUtil.templateChannelSFTP(manager, (channelSftp) -> {
                try {
                    Vector<ChannelSftp.LsEntry> vector = channelSftp.ls(messageDTO.getCommand());
                    List<SFTPFileVO> sftpFileVOS = analysisLsEntry(vector);
                    SocketMessageVO<List<SFTPFileVO>> messageVO = BeanUtil.copyProperties(socketMessageVO, SocketMessageVO.class);
                    messageVO.setType("sftp");
                    messageVO.setObj(sftpFileVOS);
                    message.sendMessage(new TextMessage(JSONUtil.toJsonStr(messageVO)));
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            });
        }catch (Exception e){
            log.error("sftp 连接失败 {}",e.getMessage());
        }
    }

    @Override
    void connect(TerminalSessionManager.Manager manager, SSHMessageDTO messageDTO) throws Exception {

    }

    @Override
    void close(TerminalSessionManager.Manager manager) {

    }

    private List<SFTPFileVO> analysisLsEntry(Vector<ChannelSftp.LsEntry> vector){
        return vector.stream().map(i -> {
            List<String> strs = Arrays.stream(i.getLongname().split(" ")).filter(str -> !str.isEmpty()).collect(Collectors.toList());
            if(i.getFilename().equals(".") || i.getFilename().equals("..")){
                return  null;
            }
            SftpATTRS sftpATTRS = i.getAttrs();
            SFTPFileVO sftp = BeanUtil.copyProperties(sftpFileVO, SFTPFileVO.class);
            sftp.setAuth(sftpATTRS.getPermissionsString());
            sftp.setNum(strs.get(1));
            sftp.setUser(strs.get(2));
            sftp.setGroup(strs.get(3));
            sftp.setSize(String.valueOf(sftpATTRS.getSize()));
            sftp.setLt(sftpATTRS.getMtimeString());
            sftp.setName(i.getFilename());
            sftp.setIsDir(sftpATTRS.isDir());
            sftp.setIsReg(sftpATTRS.isReg());
            sftp.setIsReg(sftpATTRS.isLink());
            return sftp;
        }).filter(i -> ObjectUtil.isNotEmpty(i)).collect(Collectors.toList());
    }





}
